//Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.Text;

namespace Eas.WebCrawler.PlugIns.Selectors {

    /// <summary>A delegate that takes a requests and returns <code>true</code> or <code>false</code>.</summary>
    /// <param name="request">The request to check.</param>
    /// <returns><code>true</code> or <code>false</code>.</returns>
    [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Naming", "CA1711:IdentifiersShouldNotHaveIncorrectSuffix")]
    public delegate bool RequestFilterDelegate(Eas.WebCrawler.Interfaces.Request request);

    /// <summary>A base class for selectors which selects links by calling a passed in delegate and than calling an inner selector based on the results of the delegate.</summary>
    public class ConditionalSelector : Eas.WebCrawler.Interfaces.LinkSelector{

        /// <summary>The Selector called if the conditional is True.</summary>
        /// <remarks>Backing field for the TrueSelector property.</remarks>
        /// <seealso cref="TrueSelector"/>
        private Eas.WebCrawler.Interfaces.LinkSelector _TrueSelector;

        /// <summary>The <see cref="Eas.WebCrawler.Interfaces.LinkSelector"/> called if the conditional returns <code>true</code>.</summary>
        /// <remarks>Backing field for the FalseSelector property.</remarks>
        /// <seealso cref="FalseSelector"/>
        private Eas.WebCrawler.Interfaces.LinkSelector _FalseSelector;

        /// <summary>The <see cref="Eas.WebCrawler.Interfaces.LinkSelector"/> called if the conditional returns <code>true</code>.</summary>
        public Eas.WebCrawler.Interfaces.LinkSelector FalseSelector {
            get { return _FalseSelector; }
        }

        /// <summary>The Selector called if the conditional is True.</summary>
        public Eas.WebCrawler.Interfaces.LinkSelector TrueSelector {
            get { return _TrueSelector; }
        }

        /// <summary>The delegate called to decide which selector to use.</summary>
        /// <remarks>Backing field for the ConditionalDelegate property.</remarks>
        /// <seealso cref="ConditionalDelegate"/>
        private RequestFilterDelegate _ConditionalDelegate;

        /// <summary>The delegate called to decide which selector to use.</summary>
        protected RequestFilterDelegate ConditionalDelegate {
            get { return _ConditionalDelegate; }
            set { _ConditionalDelegate = value; }
        }

        /// <summary>Constructs a selector from two inner selectors and a conditional delegate.</summary>
        /// <param name="trueSelector">The selector to call if <paramref name="filterDelegate"/> returns <code>true</code>.</param>
        /// <param name="falseSelector">The selector to call if <paramref name="filterDelegate"/> returns <code>false</code>.</param>
        /// <param name="filterDelegate">The conditional called for the two requests in order to determine which inner selector to call.</param>
        public ConditionalSelector(Eas.WebCrawler.Interfaces.LinkSelector trueSelector, Eas.WebCrawler.Interfaces.LinkSelector falseSelector, RequestFilterDelegate filterDelegate) {
            _TrueSelector = trueSelector;
            _FalseSelector = falseSelector;
            _ConditionalDelegate = filterDelegate;
        }

        #region LinkSelector Members
        /// <summary>Determines whether or not to follow the request.</summary>
        /// <param name="request">The request to check.</param>
        /// <returns><code>true</code> if the request should be crawled, otherwise <code>false</code>.</returns>
        /// <remarks>This function calls the delegate passed into the constructor, and then calls the appriopriate inner selector to decide what value to return.</remarks>
        public bool ShouldFollow(Eas.WebCrawler.Interfaces.Request request) {
            if (_ConditionalDelegate(request))
                return _TrueSelector.ShouldFollow(request);
            else
                return _FalseSelector.ShouldFollow(request);
        }

        #endregion

        #region WebCrawlerComponent Members

        /// <summary>Initializes this class</summary>
        /// <param name="context">The <see cref="Eas.WebCrawler.Interfaces.WebCrawlerContext"/> which will contain data about this instance of the web crawler.</param>
        public void Initialize(Eas.WebCrawler.Interfaces.WebCrawlerContext context) {
            _TrueSelector.Initialize(context);
            _FalseSelector.Initialize(context);
        }

        #endregion
    }
}
